package com.gwd.task.services.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.gwd.task.componts.Cache;
import com.gwd.task.entity.UserEntity;
import com.gwd.task.exception.DataException;
import com.gwd.task.exception.UnAuthorizationException;
import com.gwd.task.model.CallResultMsg;
import com.gwd.task.model.PageUtils;
import com.gwd.task.model.UserDTO;
import com.gwd.task.repository.UserRepository;
import com.gwd.task.services.UserGroupServer;
import com.gwd.task.services.UserServer;
import com.gwd.task.untils.JwtUtil;
import com.gwd.task.untils.ListPredicate;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author zhiyongming
 * @date 2020/11/10 19:41
 */
@Service
public class UserServerImpl implements UserServer {

    @Resource
    private Cache cache;
    @Resource
    private UserRepository userRepository;
    @Resource
    private UserGroupServer userGroupServer;

    @Override
    public List<UserDTO> findByGroup(Long group) {
        List<Long> idList = userGroupServer.findByGroup(group);
        if (idList.size()!=0) {
            List<UserEntity> userEntityList = userRepository.findAllById(idList);
            userEntityList = userEntityList.stream().filter(e->e.getRemove()==0).collect(Collectors.toList());
            if (!userEntityList.isEmpty()) {
                return userEntityList.stream().map(UserDTO::new).collect(Collectors.toList());
            }
        }
        return new ArrayList<>();
    }

    @Override
    public List<UserDTO> findAll(UserDTO dto) {
        List<UserEntity> all = userRepository.findAll((Specification<UserEntity>) (root, query, cb) ->
                ListPredicate.of(root, query, cb)
                        .equal("userName", dto.getUserName())
                        .equal("role", dto.getRole())
                        .equal("userId", dto.getUserId())
                        .equal("remove", dto.getRemove())
                        .equal("password", dto.getPassword())
                        .finish()
                        .getRestriction()
        );

        if (all.size()==0) {
            return new ArrayList<>();
        }

        return all.stream().map(UserDTO::new).collect(Collectors.toList());
    }

    @Override
    public List<UserDTO> findAll() {
        return userRepository.findAll().stream().map(UserDTO::new).collect(Collectors.toList());
    }

    @Override
    public PageUtils findByPage(UserDTO dto, PageUtils pageUtils) {

        Page<UserEntity> page =
                userRepository.findAll((Specification<UserEntity>)
                        (root, query, cb) ->
                                ListPredicate.of(root, query, cb)
                                        .like("userName", dto.getUserName())
                                        .finish()
                                        .getRestriction()
                , pageUtils.convert());

        List<UserDTO> list = page.get().map(UserDTO::new).collect(Collectors.toList());

        pageUtils.convert(page).setContent(list);

        return pageUtils;
    }

    @Override
    public CallResultMsg<?> login(UserDTO dto) {
        Optional<UserEntity> one = userRepository.findOne(Example.of(new UserEntity(dto)));
        if (one.isPresent()) {
            if (one.get().getRemove()==1) {
                throw new UnAuthorizationException(2);
            }
            String sign = JwtUtil.sign(one.get().getUserName(), one.get().getUserId());
            return CallResultMsg.success(sign);
        } else {
            throw new UnAuthorizationException(1);
        }
    }

    @Override
    public void save(UserDTO dto) {
        UserEntity save;
        if (dto.getUserId()!=null) {
            Optional<UserEntity> byId = userRepository.findById(dto.getUserId());
            if (!byId.isPresent()) {
                throw new DataException("userId:" + dto.getUserId() + "对应的数据不存在。");
            }
            save = byId.get();
        } else {
            Optional<UserEntity> one = userRepository.getByUserName(dto.getUserName());
            if (one.isPresent()) {
                throw new DataException("用户名" + dto.getUserName() + "已存在。");
            }
            save = new UserEntity();
        }
        BeanUtil.copyProperties(dto, save, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        cache.refresh(userRepository.save(save));
    }

    @Override
    public void reset(Long userId, String password) {
        userRepository.resetPass(password, userId);
    }

    @Override
    public void remove(Long id) {
        userRepository.findById(id).ifPresent(userEntity -> {
            userEntity.setRemove(1);
            userRepository.save(userEntity);
        });
    }

    @Override
    public void active(Long id) {
        userRepository.findById(id).ifPresent(userEntity -> {
            userEntity.setRemove(0);
            userRepository.save(userEntity);
        });
    }

    @Override
    public UserDTO findById(Long id) {
        return new UserDTO(userRepository.getOne(id));
    }
}
